import * as XLSX from 'xlsx'

const QuestionType = {
  1: 'Input',
  2: 'Radio',
  3: 'Checkbox',
  4: 'ComponentFile',
  5: 'RadioInput',
  6: 'CheckboxInput',
  7: 'Textarea',
  8: 'ComponentMultiLine',
  9: 'ComponentPolygon',
  10: 'ComponentMultiPolygon',
  11: 'ComponentBuildingChoose',
  12: 'ComponentPoint',
  13: 'DigitalInput',
  14: 'DecimalInput',
  15: 'ComponentBuilding',
  16: 'Special',
  17: 'SpecialRadio',
  18: 'VoiceFile',
  19: 'PictureRadioInput',
  20: 'SpecialCheckbox',
  21: 'BuildingTotal',
  22: 'BuildingSelf',
  23: 'ComponentLine',
  24: 'ComponentMultiPoint',
}

const baseFileUrl =
  process.env.NODE_ENV === 'development'
    ? 'http://192.168.3.37:3112'
    : window.BASE_FILE_URL

export function getColumns(questionInfo, isSpecial, isBuild) {
  let info = questionInfo.filter((x) => x.name !== '无标题')
  let resultVec = []
  // console.log(info)

  info.forEach((item) => {
    let list = item.problemInfoList || item.satisfactionInfoList

    if (list) {
      list.sort((a, b) => a.orderIndex - b.orderIndex)
      let length = list.length
      let len = list[length - 1].orderIndex
      let min = list[0].orderIndex < 0 ? list[0].orderIndex : 0

      for (let i = min; i <= len; i++) {
        let pos = list.findIndex((x) => x.orderIndex === i)
        if (pos !== -1) {
          if (isSpecial) {
            if (isBuild === 'build') {
              resultVec.push({
                question: item.name,
                unit: '|special-title|',
              })
            }
            if (isBuild === 'region') {
              resultVec.push(...getQuestionAndAnswer2(list[pos], 'region'))
            } else {
              resultVec.push(...getQuestionAndAnswer2(list[pos], []))
            }
          } else {
            resultVec.push(...getQuestionAndAnswer(list[pos]))
          }
        } else {
          let special = item.children.find(
            (x) => x.problemInfoList && x.orderIndex === i
          )
          if (special && special.name === '无标题') {
            const list = special.problemInfoList || []
            list.sort((a, b) => a.orderIndex - b.orderIndex)
            list.forEach((x) => {
              if (isSpecial) {
                if (isBuild === 'build') {
                  resultVec.push({
                    question: item.name,
                    unit: '|special-title|',
                  })
                }
                if (isBuild === 'region') {
                  resultVec.push(...getQuestionAndAnswer2(list[pos], 'region'))
                } else {
                  resultVec.push(...getQuestionAndAnswer2(list[pos], []))
                }
              } else {
                resultVec.push(...getQuestionAndAnswer(x))
              }
            })
          }
        }
      }
    }
    if (item.children.length > 0) {
      let children = item.children
      let result = getColumns(children, isSpecial, isBuild)
      resultVec.push(...result)
    }
  })

  return resultVec
}

function findAreaItemByCode(targetCode, areaInfo) {
  for (let node of areaInfo) {
    if (node.areaCode === targetCode) {
      return node
    }
    let child = findAreaItemByCode(targetCode, node.children)
    if (child) {
      return child
    }
  }
  return null
}

function getOptionsAndAnswerAndOtherArr(question, temp) {
  let contentId = temp.contentId
  let optionArr = question.problemContentInfoList.filter((x) =>
    contentId?.includes(x.pkid)
  )
  let answer = optionArr.map((x) => x.content).join(',')
  return [answer, optionArr]
}

function getQuestionAndAnswer(self) {
  let question = self.problemContent || '附加'
  let type = QuestionType[self.problemType]
  let unit = self.unit

  let resultVec = []

  let options = []
  let pkids = []

  switch (type) {
    case 'Checkbox':
    case 'Radio': {
      pkids.push(self.pkid)

      options = self.problemContentInfoList.map((x) => {
        return {
          label: x.content,
          value: x.pkid,
        }
      })
      resultVec.push({ question, pkids, options, type: self.problemType, unit })

      let result = []
      let otherResult = []
      const length = self.children.length

      for (let i = 0; i < length; i++) {
        let children = self.children[i]
        otherResult.push(...getQuestionAndAnswer(children))
      }

      let totalVec = []

      otherResult.forEach((x) => {
        const find = result.find((y) => y.question === x.question)
        if (find) {
          find.pkids.push(...x.pkids)
        } else {
          result.push(x)
        }
      })

      totalVec.push(...result)
      resultVec.push(...totalVec)
      break
    }
    case 'ComponentFile': {
      pkids.push(self.pkid)
      resultVec.push({ question, pkids, options, type: self.problemType, unit })
      break
    }
    case 'VoiceFile': {
      break
    }
    default: {
      pkids.push(self.pkid)
      resultVec.push({ question, pkids, options, type: self.problemType, unit })
      break
    }
  }

  return resultVec
}

function getQuestionAndAnswer2(self, areaInfo) {
  let question = self.problemContent || '附加'
  let type = QuestionType[self.problemType]

  const excludeType = [
    // 'ComponentFile',
    'VoiceFile',
    'ComponentPoint',
    'ComponentMultiPoint',
    'ComponentPolygon',
    'ComponentLine',
    'ComponentMultiLine',
    'ComponentMultiPolygon',
    'ComponentBuildingChoose',
    'ComponentBuilding',
  ]
  if (excludeType.includes(type)) {
    return []
  }

  let resultVec = []

  let answer = ''
  let remark = ''
  let unit = self.unit

  let temp0 =
    self.satisfactionResultInfoList ||
    self.problemResultInfoList ||
    self.regionResultInfoList

  if (!temp0 || temp0.length === 0) {
    resultVec.push({ question, answer, remark, unit })
    return resultVec
  }

  let temp = temp0[0]

  switch (type) {
    case 'Checkbox':
    case 'Radio': {
      let [answer, optionArr] = getOptionsAndAnswerAndOtherArr(self, temp)
      resultVec.push({ question, answer, remark, unit })

      let checkOrderIndexs = optionArr.map((x) => x.orderIndex)
      let result = []
      let otherResult = []

      const childrenList = self.children
      childrenList.sort((a, b) => a.orderIndex - b.orderIndex)
      const length = childrenList.length

      for (let i = 0; i < length; i++) {
        let children = self.children[i]
        let parentContentIndex = parseInt(children.parentContentIndex)
        if (checkOrderIndexs.includes(parentContentIndex)) {
          result.push(
            ...getQuestionAndAnswer2(children, areaInfo).map((x) => ({
              ...x,
              remark: i.toString(),
            }))
          )
        } else {
          otherResult.push(
            ...getQuestionAndAnswer2(children, areaInfo).map((x) => ({
              ...x,
              answer: '',
              remark: i.toString(),
            }))
          )
        }
      }

      let totalVec = []
      if (result.length === 0) {
        otherResult.forEach((x) => {
          if (!totalVec.some((y) => y.question === x.question)) {
            totalVec.push(x)
          }
        })
      } else {
        otherResult.forEach((x) => {
          if (!result.some((y) => y.question === x.question)) {
            totalVec.push(x)
          }
        })
      }

      totalVec.push(...result)
      totalVec.sort((a, b) => parseInt(a.remark) - parseInt(b.remark))
      resultVec.push(...totalVec)
      return resultVec
    }
    case 'SpecialRadio': {
      if (areaInfo === 'region') {
        answer = temp.content
      } else {
        let areaCodeVec = temp.content.split(',')
        let code = areaCodeVec[areaCodeVec.length - 1]
        let areaItem = findAreaItemByCode(code, areaInfo)
        if (areaItem) {
          answer = areaItem.areaName
        }
      }
      break
    }
    case 'ComponentFile': {
      let ls = self.satisfactionResultInfoList
        ? self.satisfactionResultInfoList
        : self.problemResultInfoList
        ? self.problemResultInfoList
        : self.regionResultInfoList
      answer = ls
        .filter((x) => x.filePath)
        .map((x) => baseFileUrl + x.filePath)
        .join(',')
      unit = '|special-file|'
      break
    }
    case 'VoiceFile':
      break
    case 'ComponentPoint':
    case 'ComponentMultiPoint':
    case 'ComponentPolygon':
    case 'ComponentLine':
    case 'ComponentMultiLine':
    case 'ComponentMultiPolygon': {
      // answer = temp.otherContent
      break
    }
    case 'ComponentBuilding':
    case 'ComponentBuildingChoose': {
      break
    }
    default: {
      answer = temp.content
      break
    }
  }

  resultVec.push({ question, answer, remark, unit })
  return resultVec
}

export function _getExcelData(questions, infos, result, areaInfo, special) {
  if (!infos) return
  Object.keys(infos).forEach((phone) => {
    const rows = [[]]
    let row = rows[0]
    if (special === 'street') {
      if (infos[phone]?.length) {
        const item = infos[phone][0]
        row.push(item.regionname)
        row.push(item.streetname)
      }
    } else {
      row.push(phone)
    }
    questions.forEach((question) => {
      let list = infos[phone]
        .filter((x) => question.pkids.includes(x.problem_id))
        .sort((a, b) => {
          if (a.group_index < b.group_index) {
            return -1
          }
          if (a.group_index > b.group_index) {
            return 1
          }
          return 0
        })

      const type = QuestionType[question.type]
      if (list.length > 1 && type !== 'ComponentFile' && type !== 'VoiceFile') {
        // 判断总共需要加几行
        const len = list.length - 1
        for (let i = 0; i < len; i++) {
          // 读取第一行已经加入的列数
          const length = row.length
          let j = 1
          // 如果已经添加了新的一行
          if (rows[i + 1]) {
            // 将此行已经有的长度作为起始点
            j = rows[i + 1].length
          } else {
            // 如果未添加新的一行
            if (special === 'street') {
              if (infos[phone]?.length) {
                const item = infos[phone][0]
                rows.push([item.regionname, item.streetname])
                j = 2
              }
            } else {
              rows.push([phone])
            }
          }
          for (; j < length; j++) {
            rows[i + 1].push('')
          }
        }
      }
      switch (type) {
        case 'Checkbox':
        case 'Radio': {
          list.forEach((x, i) => {
            const answer = question.options
              .filter((y) => x.content_id?.includes(y.value))
              .map((y) => y.label)
              .filter((y) => !!y)
              .join(',')
            rows[i].push(answer)
          })
          break
        }
        case 'SpecialRadio': {
          list.forEach((x, i) => {
            const areaCodeArr = x.content?.split(',')
            let answer = ''
            if (areaCodeArr?.length) {
              const code = areaCodeArr[areaCodeArr.length - 1]
              const item = findAreaItemByCode(code, areaInfo)
              answer = item ? item.areaName : ''
            }
            rows[i].push(answer)
          })
          break
        }
        case 'ComponentFile': {
          const answer = list
            .filter((x) => x.file_path)
            .map((x) => {
              return `${baseFileUrl}${x.file_path}`
            })
            .filter((x) => !!x)
            .join(',')
          row.push(answer)
          break
        }
        // case 'VoiceFile':
        //   break
        // case 'ComponentPoint':
        // case 'ComponentPolygon':
        // case 'ComponentLine':
        // case 'ComponentMultiPolygon': {
        //   list.forEach((x, i) => {
        //     const answer = x.other_content
        //     rows[i].push(answer)
        //   })
        //   break
        // }
        default: {
          list.forEach((x, i) => {
            rows[i].push(x.content)
          })
          break
        }
      }
    })
    result.push(...rows)
  })
}

export function getExcelData(questions, infos, result, areaInfo, special) {
  if (!infos) return
  Object.keys(infos).forEach((phone) => {
    let row = []
    if (special === 'street') {
      if (infos[phone]?.length) {
        const item = infos[phone][0]
        row.push(item.regionname)
        row.push(item.streetname)
      }
    } else {
      row.push(phone)
    }
    questions.forEach((question) => {
      let list = infos[phone].filter((x) =>
        question.pkids.includes(x.problem_id)
      )

      const type = QuestionType[question.type]
      switch (type) {
        case 'Checkbox':
        case 'Radio': {
          const answer = list
            .map((x) => {
              return question.options.find((y) =>
                x.content_id?.includes(y.value)
              )?.label
            })
            .filter((x) => !!x)
            .toString()
          row.push(answer)
          break
        }
        case 'SpecialRadio': {
          const answer = list
            .map((x) => {
              const areaCodeArr = x.content?.split(',')
              if (areaCodeArr?.length) {
                const code = areaCodeArr[areaCodeArr.length - 1]
                const item = findAreaItemByCode(code, areaInfo)
                return item ? item.areaName : ''
              }
            })
            .filter((x) => !!x)
            .toString()
          row.push(answer)
          break
        }
        case 'ComponentFile': {
          const answer = list
            .map((x) => {
              return `${baseFileUrl}${x.file_path}`
            })
            .filter((x) => !!x)
            .join(',')
          row.push(answer)
          break
        }
        case 'VoiceFile':
          break
        case 'ComponentPoint':
        case 'ComponentMultiPoint':
        case 'ComponentPolygon':
        case 'ComponentLine':
        case 'ComponentMultiLine':
        case 'ComponentMultiPolygon': {
          const answer = list
            .map((x) => {
              return x.other_content
            })
            .filter((x) => !!x)
            .join(',')
          row.push(answer)
          break
        }
        default: {
          let answer = list
            .map((x) => x.content)
            .filter((x) => !!x)
            .join(',')
          row.push(answer)
          break
        }
      }
    })
    result.push(row)
  })
}

export function sheet2blob(sheetInfos) {
  if (!sheetInfos) return

  const sheetNames = []
  const sheets = {}
  sheetInfos.forEach((sheetInfo) => {
    const sheetName = sheetInfo.sheetName || 'Sheet1'
    sheetNames.push(sheetName)
    sheets[sheetName] = sheetInfo.sheet // 生成excel的配置项
  })

  const workbook = {
    SheetNames: sheetNames,
    Sheets: sheets,
  }

  const wopts = {
    bookType: 'xlsx', // 要生成的文件类型
    bookSST: false, // 是否生成Shared String Table，官方解释是，如果开启生成速度会下降，但在低版本IOS设备上有更好的兼容性
    type: 'binary',
  }
  const wbout = XLSX.write(workbook, wopts)

  // 字符串转ArrayBuffer
  function s2ab(s) {
    const buf = new ArrayBuffer(s.length)
    const view = new Uint8Array(buf)
    for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xff
    return buf
  }

  return new Blob([s2ab(wbout)], {
    type: 'application/octet-stream',
  })
}

export function getSpecialQuestion(list) {
  const data = list[0]?.children
  const dict = {}
  data?.forEach((item) => {
    const value = []
    item.problemInfoList?.forEach((v) => {
      value.push(...getQuestionAndAnswer(v))
    })
    dict[item.name] = value
  })
  return dict
}

export function getSpecialExcelData(
  questions,
  infos,
  areaInfo,
  headerFirst,
  special
) {
  const sheetInfos = []
  Object.keys(questions).forEach((key) => {
    const sheetName = key
    const res = []
    const question = questions[key]
    if (special === 'street') {
      const header = [...headerFirst]
      question.forEach((item) => {
        header.push(item.question)
      })
      res.push(header)
    } else {
      if (headerFirst) {
        let header = []
        if (Array.isArray(headerFirst)) {
          header = [[...headerFirst]]
        } else {
          header = [headerFirst]
        }
        question.forEach((item) => {
          header.push(item.question)
        })
        res.push(header)
      }
    }

    _getExcelData(question, infos, res, areaInfo, special)
    sheetInfos.push({
      sheetName,
      sheet: XLSX.utils.aoa_to_sheet(res),
    })
  })
  return sheetInfos
}

export function getSpecialColumns(questionInfo, type) {
  let base
  let list
  let specialList = []
  if (type.includes('region-')) {
    const item = questionInfo || []
    list = item.map((val) => {
      return {
        ...val,
        children: [],
      }
    })
    specialList = item[0]?.children || []
  } else {
    base = questionInfo[0]?.children[0]?.children || []
    list = []
    base.forEach((item) => {
      if (
        (item.pkid !== 'new31' &&
          item.pkid !== '315' &&
          type === 'community') ||
        (item.pkid === '410' && type === 'street')
      ) {
        specialList.push(item)
      } else {
        list.push(item)
      }
    })
  }

  let resultBase
  if (type.includes('region-')) {
    resultBase = getColumns(list, true, 'region')
  } else {
    resultBase = getColumns(list, true)
  }
  if (type === 'street') {
    specialList = specialList[0]?.children || []
  }
  const resultSpecial = specialList.map((special) => {
    const questions = []
    const resultInfoList = []
    const problemInfoList = special.problemInfoList || []
    problemInfoList.sort((a, b) => a.orderIndex - b.orderIndex)
    problemInfoList.forEach((info) => {
      questions.push(...getQuestionAndAnswer(info))
      if (type.includes('region-')) {
        resultInfoList.push(...info.regionResultInfoList)
      } else {
        resultInfoList.push(...info.problemResultInfoList)
      }
    })
    const idCount = {}
    resultInfoList.forEach((obj) => {
      if (idCount[obj.groupIndex]) {
        idCount[obj.groupIndex]++
      } else {
        idCount[obj.groupIndex] = 1
      }
    })

    const children = []

    Object.keys(idCount).forEach((groupIndex) => {
      const child = []
      questions.forEach((question) => {
        const type = QuestionType[question.type]
        let unit = question.unit
        const fileExclude = [
          'VoiceFile',
          'ComponentBuilding',
          'ComponentBuildingChoose',
        ]
        const excludeType = [
          // 'ComponentFile',
          'ComponentPoint',
          'ComponentPolygon',
          'ComponentLine',
          'ComponentMultiPolygon',
        ]
        if (
          fileExclude.includes(type) &&
          (excludeType.includes(type) || type.includes('region-'))
        ) {
          return
        }
        const list = resultInfoList.filter(
          (x) =>
            question.pkids.includes(x.problemId) && x.groupIndex === groupIndex
        )
        let answer = ''
        switch (type) {
          case 'Checkbox':
          case 'Radio': {
            answer = list
              .map((x) => {
                return question.options.find((y) =>
                  x.contentId?.includes(y.value)
                )?.label
              })
              .filter((x) => !!x)
              .toString()
            break
          }
          case 'SpecialRadio':
            break
          case 'ComponentFile':
            {
              answer = list
                .filter((x) => x.filePath)
                .map((x) => {
                  return `${baseFileUrl}${x.filePath}`
                })
                .join(',')
              // console.log(answer)
              unit = '|special-file|'
            }
            break
          case 'VoiceFile':
            break
          case 'ComponentPoint':
          case 'ComponentPolygon':
          case 'ComponentLine':
          case 'ComponentMultiPolygon': {
            answer = list.map((x) => x.content).filter((x) => !!x).length
              ? '已绘制'
              : '未绘制'
            break
          }
          default: {
            answer = list
              .map((x) => x.content)
              .filter((x) => !!x)
              .join(',')
            break
          }
        }
        child.push({ question: question.question, answer, unit })
      })
      children.push(child)
    })
    return {
      name: special.name,
      children,
    }
  })
  return {
    base: resultBase,
    special: resultSpecial,
  }
}
